#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <functional>
#include <pthread.h>
#include "log.hpp"
#include "InetAddr.hpp"
#include "socket.hpp"

class tcpserver;
// 哪个套接字                  哪个客户端来的
using io_service_t = std::function<void(std::shared_ptr<net::Socket> sockfd, InetAddr client)>;

class ThreadData
{
public:
    ThreadData(net::socket_ptr sockfd, InetAddr addr, tcpserver *s)
        : _sockfd(sockfd), _addr(addr), _s(s)
    {
    }
    net::socket_ptr _sockfd;
    InetAddr _addr;
    tcpserver *_s;
};

class tcpserver
{
public:
    tcpserver(uint16_t port, io_service_t service)
        : _listenSockPtr(std::make_unique<net::TcpSocket>()), _localaddr("0", port), isrunning(false), _service(service)
    {
        _listenSockPtr->BuildServerSocket(_localaddr);
    }

    static void *threadsocktask(void *argc)
    {
        ThreadData *p = (ThreadData *)argc;
        p->_s->_service(p->_sockfd, p->_addr);
        ::close(p->_sockfd->SockFd());
        delete p;
        return nullptr;
    }

    void start()
    {
        isrunning = true;
        while (isrunning)
        {
            InetAddr addr;
            net::socket_ptr sockptr = _listenSockPtr->Accept(&addr);
            if (sockptr == nullptr)
            {
                continue;
            }

            // 版本三:多线程
            pthread_t id;
            ThreadData *data = new ThreadData(sockptr, addr, this);
            pthread_create(&id, nullptr, &threadsocktask, data);
            pthread_detach(id);
        }
        isrunning = false;
    }

private:
    std::unique_ptr<net::Socket> _listenSockPtr;
    InetAddr _localaddr;
    bool isrunning;

    io_service_t _service;
};
